import { Image, UploadFile } from 'antd';
import { MutableRefObject, useEffect, useMemo, useState } from 'react';
import { getIUPFilePreviewUrl, iup, PlusOutlined, useRefCallback } from '../../../../../../util';
import { AttachmentFile, DEFAULT_ATTACHMENT_UPLOAD_MAX_COUNT, UploadedFile } from '../../../../AttachmentContext';
import { Upload, UploadProps } from '../../../../components';

const getBase64 = (prefix: string, str: string) => {
  const content = Buffer.from(str, 'utf8').toString('base64');
  return `${prefix};base64,${content}`;
};

const isConvertBase64 = (name: string) => {
  if (!name) {
    return false;
  }
  if (name.endsWith('.svg') || name.endsWith('.svgz')) {
    return true;
  }
  return false;
};

function useImageUpload(attachmentFileList: AttachmentFile[] = []) {
  const [fileList, setFileList] = useState<UploadFile[]>([]);
  const [previewImage, setPreviewImage] = useState('');
  const [previewOpen, setPreviewOpen] = useState(false);

  const transformFile = useRefCallback((data) => {
    const url = getIUPFilePreviewUrl(data.asrFid).url;
    const extra = isConvertBase64(data.fileName || data.asrName)
      ? {
          originFileObj: new File(data.asrFid ? [data.asrFid] : [], url)
        }
      : { url };

    return {
      uid: data.asrFid || data.fileName,
      name: data.fileName,
      ...data,
      ...extra
    } as UploadFile;
  });

  useEffect(() => {
    if (Array.isArray(attachmentFileList)) {
      const list = [...attachmentFileList].reverse().filter((v) => v.status !== 'fail' && v.status !== 'error');
      setFileList((pre) => {
        return list.map((item, index) => {
          if (pre[index] && pre[index].uid === (item as UploadedFile).asrFid) {
            return pre[index];
          }
          return transformFile(item);
        });
      });
    }
  }, [attachmentFileList]);

  const previewOptions = useMemo(() => {
    return {
      handlePreview: (file: UploadFile) => {
        if (!file.url && !file.preview && !file.thumbUrl) {
          console.log('preview file required url', file);
        } else {
          setPreviewImage(file.thumbUrl || file.preview || file.url || '');
          setPreviewOpen(true);
        }
      },
      onVisibleChange: (value: boolean, prevValue: boolean) => setPreviewOpen(value),
      afterOpenChange: (open: boolean) => !open && setPreviewImage('')
    };
  }, []);

  const previewFile = async (file: File | Blob) => {
    if (file instanceof File && file.size > 0) {
      const res = await iup.request.get({ url: (file as File).name });
      return getBase64('data:image/svg+xml', res as any);
    }
    return Promise.resolve('');
  };

  const preview = {
    open: previewOpen,
    image: previewImage,
    ...previewOptions
  };

  return [fileList, { preview, previewFile }] as const;
}
const defaultAccept = '.png,.jpg,.jpeg,.svg';
interface ImageUploadProps
  extends Pick<UploadProps, 'onUploaded' | 'onUploadStateChange' | 'onBeforeUpload' | 'onRemove' | 'disabled'> {
  attachmentFileList: AttachmentFile[];
  uploadRef: MutableRefObject<any>;
  accept?: string;
  maxCount?: number;
}
export function ImageUpload(props: ImageUploadProps) {
  const {
    attachmentFileList,
    uploadRef,
    accept = defaultAccept,
    maxCount = DEFAULT_ATTACHMENT_UPLOAD_MAX_COUNT,
    onRemove,
    onUploadStateChange,
    onBeforeUpload,
    onUploaded,
    disabled
  } = props;
  const [files, { preview, previewFile }] = useImageUpload(attachmentFileList);
  return (
    <>
      <Upload
        disabled={disabled}
        onUploadStateChange={onUploadStateChange}
        onUploaded={onUploaded}
        onBeforeUpload={onBeforeUpload}
        accept={accept}
        ref={uploadRef}
        containerStyles={{ display: 'inherit' }}
        onPreview={preview.handlePreview}
        showUploadList={true}
        listType="picture-card"
        fileList={files}
        onRemove={onRemove}
        previewFile={previewFile}
      >
        {files.length >= maxCount ? null : (
          <button style={{ border: 0, background: 'none' }} type="button">
            <PlusOutlined />
            <div style={{ marginTop: 8 }}>上传图片</div>
          </button>
        )}
      </Upload>
      {preview.image && (
        <Image
          wrapperStyle={{ display: 'none' }}
          preview={{
            visible: preview.open,
            onVisibleChange: preview.onVisibleChange,
            afterOpenChange: preview.afterOpenChange
          }}
          src={preview.image}
        />
      )}
    </>
  );
}
